home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / gnuplot / readline.c < prev    next >
C/C++ Source or Header  |  1993-09-15  |  22KB  |  957 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: readline.c%v 3.50.1.9 1993/08/05 05:38:59 woo Exp $";
  3. #endif
  4.  
  5.  
  6. /* GNUPLOT - readline.c */
  7. /*
  8.  * Copyright (C) 1986 - 1993   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted, 
  12.  * provided that the above copyright notice appear in all copies and 
  13.  * that both that copyright notice and this permission notice appear 
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the modified code.  Modifications are to be distributed 
  18.  * as patches to released version.
  19.  *  
  20.  * This software is provided "as is" without express or implied warranty.
  21.  * 
  22.  *
  23.  * AUTHORS
  24.  *
  25.  *   Original Software:
  26.  *     Tom Tkacik
  27.  *
  28.  *   Msdos port and some enhancements:
  29.  *     Gershon Elber and many others.
  30.  * 
  31.  * There is a mailing list for gnuplot users. Note, however, that the
  32.  * newsgroup 
  33.  *    comp.graphics.gnuplot 
  34.  * is identical to the mailing list (they
  35.  * both carry the same set of messages). We prefer that you read the
  36.  * messages through that newsgroup, to subscribing to the mailing list.
  37.  * (If you can read that newsgroup, and are already on the mailing list,
  38.  * please send a message info-gnuplot-request@dartmouth.edu, asking to be
  39.  * removed from the mailing list.)
  40.  *
  41.  * The address for mailing to list members is
  42.  *       info-gnuplot@dartmouth.edu
  43.  * and for mailing administrative requests is 
  44.  *       info-gnuplot-request@dartmouth.edu
  45.  * The mailing list for bug reports is 
  46.  *       bug-gnuplot@dartmouth.edu
  47.  * The list of those interested in beta-test versions is
  48.  *       info-gnuplot-beta@dartmouth.edu
  49.  */
  50.  
  51. #ifdef READLINE
  52. #ifdef ATARI
  53. #include "plot.h"
  54. #endif
  55. #ifdef _WINDOWS
  56. #define _Windows
  57. #endif
  58.  
  59. /* a small portable version of GNU's readline */
  60. /* this is not the BASH or GNU EMACS version of READLINE due to Copyleft 
  61.     restrictions */
  62. /* do not need any terminal capabilities except backspace, */
  63. /* and space overwrites a character */
  64.  
  65. /* NANO-EMACS line editing facility */
  66. /* printable characters print as themselves (insert not overwrite) */
  67. /* ^A moves to the beginning of the line */
  68. /* ^B moves back a single character */
  69. /* ^E moves to the end of the line */
  70. /* ^F moves forward a single character */
  71. /* ^K kills from current position to the end of line */
  72. /* ^P moves back through history */
  73. /* ^N moves forward through history */
  74. /* ^H and DEL delete the previous character */
  75. /* ^D deletes the current character, or EOF if line is empty */
  76. /* ^L/^R redraw line in case it gets trashed */
  77. /* ^U kills the entire line */
  78. /* ^W kills last word */
  79. /* LF and CR return the entire line regardless of the cursor postition */
  80. /* EOF with an empty line returns (char *)NULL */
  81.  
  82. /* all other characters are ignored */
  83.  
  84. #include <stdio.h>
  85. #include <ctype.h>
  86. #include <signal.h>
  87.  
  88. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  89.  
  90. /*
  91.  * Set up structures using the proper include file
  92.  */
  93. #if defined(_IBMR2) || defined(alliant)
  94. #define SGTTY
  95. #endif
  96.  
  97. /*  submitted by Francois.Dagorn@cicb.fr */
  98. #ifdef SGTTY
  99. #include <sgtty.h>
  100. static struct sgttyb orig_termio, rl_termio;
  101. /* define terminal control characters */
  102. static struct tchars s_tchars;
  103. #define VERASE    0
  104. #define VEOF      1
  105. #define VKILL     2
  106. #ifdef TIOCGLTC         /* available only with the 'new' line discipline */
  107. static struct ltchars s_ltchars;
  108. #define VWERASE   3
  109. #define VREPRINT  4
  110. #define VSUSP     5
  111. #endif /* TIOCGLTC */
  112. #define NCCS      6
  113.  
  114. #else /* SGTTY */
  115.  
  116. /* SIGTSTP defines job control */
  117. /* if there is job control then we need termios.h instead of termio.h */
  118. /* (Are there any systems with job control that use termio.h?  I hope not.) */
  119. #ifdef SIGTSTP
  120. #define TERMIOS
  121. #include <termios.h>
  122. /* Added by Robert Eckardt, RobertE@beta.TP2.Ruhr-Uni-Bochum.de */
  123. #ifdef ISC22
  124. #ifndef ONOCR            /* taken from sys/termio.h */
  125. #define ONOCR 0000020    /* true at least for ISC 2.2 */
  126. #endif 
  127. #ifndef IUCLC
  128. #define IUCLC 0001000
  129. #endif
  130. #endif /* ISC22 */
  131.  
  132. static struct termios orig_termio, rl_termio;
  133. #else
  134. #include <termio.h>
  135. static struct termio orig_termio, rl_termio;
  136. /* termio defines NCC instead of NCCS */
  137. #define NCCS    NCC
  138. #endif /* SIGTSTP */
  139. #endif /* SGTTY */
  140.  
  141. /* ULTRIX defines VRPRNT instead of VREPRINT */
  142. #ifdef VRPRNT
  143. #define VREPRINT VRPRNT
  144. #endif
  145.  
  146. /* define characters to use with our input character handler */
  147. static char term_chars[NCCS];
  148.  
  149. static int term_set = 0;    /* =1 if rl_termio set */
  150.  
  151. #define special_getc() ansi_getc()
  152. static char ansi_getc();
  153.  
  154. #else /* !MSDOS && !ATARI && !_Windows */
  155.  
  156. #ifdef _Windows
  157. #include <windows.h>
  158. #include "win/wtext.h"
  159. #include "win/wgnuplib.h"
  160. extern TW textwin;
  161. #define TEXTUSER 0xf1
  162. #define TEXTGNUPLOT 0xf0
  163. #define special_getc() msdos_getch()
  164. static char msdos_getch();
  165. #endif
  166.  
  167. #if defined(MSDOS) || defined(DOS386)
  168. /* MSDOS specific stuff */
  169. #ifdef DJGPP
  170. #include <pc.h>
  171. #endif
  172. #ifdef __EMX__
  173. #include <conio.h>
  174. #endif
  175. #define special_getc() msdos_getch()
  176. static char msdos_getch();
  177. #endif /* MSDOS */
  178.  
  179. #ifdef ATARI
  180. #include <stdlib.h>
  181. #ifdef __PUREC__
  182. #include <tos.h>
  183. #else
  184. #include <osbind.h>
  185. #endif
  186. #define special_getc() tos_getch()
  187. static char tos_getch();
  188. #endif
  189.  
  190. #endif /* !MSDOS && !ATARI && !_Windows */
  191.  
  192. #if !defined(ATARI)
  193. /* is it <string.h> or <strings.h>?   just declare what we need */
  194. extern int      strlen();
  195. extern char *strcpy();
  196. #endif
  197. extern char *alloc();    /* we'll use the safe malloc from misc.c */
  198.  
  199. #define MAXBUF    1024
  200. #define BACKSPACE 0x08    /* ^H */
  201. #define SPACE    ' '
  202.  
  203. struct hist {
  204.     char *line;
  205.     struct hist *prev;
  206.     struct hist *next;
  207. };
  208.  
  209. static struct hist *history = NULL;  /* no history yet */
  210. static struct hist *cur_entry = NULL;
  211.  
  212. static char cur_line[MAXBUF];  /* current contents of the line */
  213. static int cur_pos = 0;    /* current position of the cursor */
  214. static int max_pos = 0;    /* maximum character position */
  215.  
  216.  
  217. void add_history();
  218. static void fix_line();
  219. static void redraw_line();
  220. static void clear_line();
  221. static void clear_eoline();
  222. static void copy_line();
  223. static void set_termio();
  224. static void reset_termio();
  225.  
  226. /* user_putc and user_puts should be used in the place of
  227.  * fputc(ch,stderr) and fputs(str,stderr) for all output
  228.  * of user typed characters.  This allows MS-Windows to 
  229.  * display user input in a different color. */
  230. int
  231. user_putc(ch)
  232. int ch;
  233. {
  234.     int rv;
  235. #ifdef _Windows
  236.     TextAttr(&textwin,TEXTUSER);
  237. #endif
  238.     rv = fputc(ch, stderr);
  239. #ifdef _Windows
  240.     TextAttr(&textwin,TEXTGNUPLOT);
  241. #endif
  242.     return rv;
  243. }
  244.  
  245. int
  246. user_puts(str)
  247. char *str;
  248. {
  249.     int rv;
  250. #ifdef _Windows
  251.     TextAttr(&textwin,TEXTUSER);
  252. #endif
  253.     rv = fputs(str, stderr);
  254. #ifdef _Windows
  255.     TextAttr(&textwin,TEXTGNUPLOT);
  256. #endif
  257.     return rv;
  258. }
  259.  
  260. /* This function provides a centralized non-destructive backspace capability */
  261. /* M. Castro */
  262.  
  263. backspace()
  264. {
  265.     user_putc(BACKSPACE);
  266. }
  267.     
  268. char *
  269. readline(prompt)
  270. char *prompt;
  271. {
  272.  
  273.     unsigned char cur_char;
  274.     char *new_line;
  275.     /* unsigned char *new_line; */
  276.  
  277.     /* set the termio so we can do our own input processing */
  278.     set_termio();
  279.  
  280.     /* print the prompt */
  281.     fputs(prompt, stderr);
  282.     cur_line[0] = '\0';
  283.     cur_pos = 0;
  284.     max_pos = 0;
  285.     cur_entry = NULL;
  286.  
  287.     /* get characters */
  288.     for(;;) {
  289.         cur_char = special_getc();
  290. #ifdef OS2
  291.  /* for emx: remap scan codes for cursor keys */
  292.                 if( cur_char == 0 ) {
  293.                     cur_char = getc(stdin);
  294.                     switch( cur_char){
  295.                         case 75:  /* left, map to ^B */
  296.                             cur_char=2;
  297.                             break ;
  298.                         case 77:  /* right, map to ^F */
  299.                             cur_char=6;
  300.                             break ;
  301.                         case 115: /* ctrl left */
  302.                         case 71:  /* home, map to ^A */
  303.                             cur_char=1;
  304.                             break ;
  305.                         case 116: /* ctrl right */
  306.                         case 79:  /* end, map to ^E */
  307.                             cur_char=5;
  308.                             break ;
  309.                         case 72:  /* up, map to ^P */
  310.                             cur_char=16;
  311.                             break ;
  312.                         case 80:  /* down, map to ^N */
  313.                             cur_char=14;
  314.                             break ;
  315.                         case 83:  /* delete, map to ^D */
  316.                             cur_char=4;
  317.                             break ;
  318.                         default:  /* ignore */
  319.                             cur_char=0;
  320.                             continue ;
  321.                             }
  322.                         }
  323. #endif  /*OS2*/
  324.         if((isprint(cur_char) 
  325. #if defined(ATARI) || defined(_Windows) || defined(MSDOS) || defined(DOS386)
  326.    /* this should be used for all 8bit ASCII machines, I guess */
  327.                     || ((unsigned char)cur_char > 0x7f)
  328. #endif
  329.                                )&& max_pos<MAXBUF-1) {
  330.             int i;
  331.             for(i=max_pos; i>cur_pos; i--) {
  332.                 cur_line[i] = cur_line[i-1];
  333.             }
  334.             user_putc(cur_char);
  335.             cur_line[cur_pos] = cur_char;
  336.             cur_pos += 1;
  337.             max_pos += 1;
  338.             if (cur_pos < max_pos)
  339.                 fix_line();
  340.             cur_line[max_pos] = '\0';
  341.  
  342.         /* else interpret unix terminal driver characters */
  343. #ifdef VERASE
  344.         } else if(cur_char == term_chars[VERASE] ){  /* DEL? */
  345.             if(cur_pos > 0) {
  346.                 int i;
  347.                 cur_pos -= 1;
  348.                 backspace();
  349.                 for(i=cur_pos; i<max_pos; i++)
  350.                     cur_line[i] = cur_line[i+1];
  351.                 max_pos -= 1;
  352.                 fix_line();
  353.             }
  354. #endif /* VERASE */
  355. #ifdef VEOF
  356.         } else if(cur_char == term_chars[VEOF] ){   /* ^D? */
  357.             if(max_pos == 0) {
  358.                 reset_termio();
  359.                 return((char *)NULL);
  360.             }
  361.             if((cur_pos < max_pos)&&(cur_char == 004)) { /* ^D */
  362.                 int i;
  363.                 for(i=cur_pos; i<max_pos; i++)
  364.                     cur_line[i] = cur_line[i+1];
  365.                 max_pos -= 1;
  366.                 fix_line();
  367.             }
  368. #endif /* VEOF */
  369. #ifdef VKILL
  370.         } else if(cur_char == term_chars[VKILL] ){  /* ^U? */
  371.             clear_line(prompt);
  372. #endif /* VKILL */
  373. #ifdef VWERASE
  374.         } else if(cur_char == term_chars[VWERASE] ){  /* ^W? */
  375.             while((cur_pos > 0) &&
  376.                   (cur_line[cur_pos-1] == SPACE)) {
  377.                 cur_pos -= 1;
  378.                 backspace();
  379.             }
  380.             while((cur_pos > 0) &&
  381.                   (cur_line[cur_pos-1] != SPACE)) {
  382.                 cur_pos -= 1;
  383.                 backspace();
  384.             }
  385.             clear_eoline();
  386.             max_pos = cur_pos;
  387. #endif /* VWERASE */
  388. #ifdef VREPRINT
  389.         } else if(cur_char == term_chars[VREPRINT] ){  /* ^R? */
  390.             putc('\n',stderr); /* go to a fresh line */
  391.             redraw_line(prompt);
  392. #endif /* VREPRINT */
  393. #ifdef VSUSP
  394.         } else if(cur_char == term_chars[VSUSP]) {
  395.             reset_termio();
  396.             kill(0, SIGTSTP);
  397.  
  398.             /* process stops here */
  399.  
  400.             set_termio();
  401.             /* print the prompt */
  402.             redraw_line(prompt);
  403. #endif /* VSUSP */
  404.         } else {
  405.             /* do normal editing commands */
  406.             /* some of these are also done above */
  407.             int i;
  408.             switch(cur_char) {
  409.                 case EOF:
  410.                 reset_termio();
  411.                 return((char *)NULL);
  412.                 case 001: /* ^A */
  413.                 while(cur_pos > 0) {
  414.                     cur_pos -= 1;
  415.                     backspace();
  416.                 }
  417.                 break;
  418.                 case 002: /* ^B */
  419.                 if(cur_pos > 0) {
  420.                     cur_pos -= 1;
  421.                     backspace();
  422.                 }
  423.                 break;
  424.                 case 005: /* ^E */
  425.                 while(cur_pos < max_pos) {
  426.                     user_putc(cur_line[cur_pos]);
  427.                     cur_pos += 1;
  428.                 }
  429.                 break;
  430.                 case 006: /* ^F */
  431.                 if(cur_pos < max_pos) {
  432.                     user_putc(cur_line[cur_pos]);
  433.                     cur_pos += 1;
  434.                 }
  435.                 break;
  436.                 case 013: /* ^K */
  437.                 clear_eoline();
  438.                 max_pos = cur_pos;
  439.                 break;
  440.                 case 020: /* ^P */
  441.                 if(history != NULL) {
  442.                     if(cur_entry == NULL) {
  443.                         cur_entry = history;
  444.                         clear_line(prompt);
  445.                         copy_line(cur_entry->line);
  446.                     } else if(cur_entry->prev != NULL) {
  447.                         cur_entry = cur_entry->prev;
  448.                         clear_line(prompt);
  449.                         copy_line(cur_entry->line);
  450.                     }
  451.                 }
  452.                 break;
  453.                 case 016: /* ^N */
  454.                 if(cur_entry != NULL) {
  455.                     cur_entry = cur_entry->next;
  456.                     clear_line(prompt);
  457.                     if(cur_entry != NULL) 
  458.                         copy_line(cur_entry->line);
  459.                     else
  460.                         cur_pos = max_pos = 0;
  461.                 }
  462.                 break;
  463.                 case 014: /* ^L */
  464.                 case 022: /* ^R */
  465.                 putc('\n',stderr); /* go to a fresh line */
  466.                 redraw_line(prompt);
  467.                 break;
  468.                 case 0177: /* DEL */
  469.                 case 010: /* ^H */
  470.                 if(cur_pos > 0) {
  471.                     cur_pos -= 1;
  472.                     backspace();
  473.                     for(i=cur_pos; i<max_pos; i++)
  474.                         cur_line[i] = cur_line[i+1];
  475.                     max_pos -= 1;
  476.                     fix_line();
  477.                 }
  478.                 break;
  479.                 case 004: /* ^D */
  480.                 if(max_pos == 0) {
  481.                     reset_termio();
  482.                     return((char *)NULL);
  483.                 }
  484.                 if(cur_pos < max_pos) {
  485.                     for(i=cur_pos; i<max_pos; i++)
  486.                         cur_line[i] = cur_line[i+1];
  487.                     max_pos -= 1;
  488.                     fix_line();
  489.                 }
  490.                 break;
  491.                 case 025:  /* ^U */
  492.                 clear_line(prompt);
  493.                 break;
  494.                 case 027:  /* ^W */
  495.                 while((cur_pos > 0) &&
  496.                       (cur_line[cur_pos-1] == SPACE)) {
  497.                     cur_pos -= 1;
  498.                     backspace();
  499.                 }
  500.                 while((cur_pos > 0) &&
  501.                       (cur_line[cur_pos-1] != SPACE)) {
  502.                     cur_pos -= 1;
  503.                     backspace();
  504.                 }
  505.                 clear_eoline();
  506.                 max_pos = cur_pos;
  507.                 break;
  508.                 case '\n': /* ^J */
  509.                 case '\r': /* ^M */
  510.                 cur_line[max_pos+1] = '\0';
  511.                 putc('\n', stderr);
  512.                 new_line = (char *)alloc((unsigned long) (strlen(cur_line)+1), "history");
  513.                 strcpy(new_line,cur_line);
  514.                 reset_termio();
  515.                 return(new_line);
  516.                 default:
  517.                 break;
  518.             }
  519.         }
  520.     }
  521. }
  522.  
  523. /* fix up the line from cur_pos to max_pos */
  524. /* do not need any terminal capabilities except backspace, */
  525. /* and space overwrites a character */
  526. static void
  527. fix_line()
  528. {
  529.     int i;
  530.  
  531.     /* write tail of string */
  532.     for(i=cur_pos; i<max_pos; i++)
  533.         user_putc(cur_line[i]);
  534.  
  535.     /* write a space at the end of the line in case we deleted one */
  536.     user_putc(SPACE);
  537.  
  538.     /* backup to original position */
  539.     for(i=max_pos+1; i>cur_pos; i--)
  540.         backspace();
  541.  
  542. }
  543.  
  544. /* redraw the entire line, putting the cursor where it belongs */
  545. static void
  546. redraw_line(prompt)
  547. char *prompt;
  548. {
  549.     int i;
  550.  
  551.     fputs(prompt, stderr);
  552.     user_puts(cur_line);
  553.  
  554.     /* put the cursor where it belongs */
  555.     for(i=max_pos; i>cur_pos; i--)
  556.         backspace();
  557. }
  558.  
  559. /* clear cur_line and the screen line */
  560. static void
  561. clear_line(prompt)
  562. char *prompt;
  563. {
  564.     int i;
  565.     for(i=0; i<max_pos; i++)
  566.         cur_line[i] = '\0';
  567.  
  568.     for(i=cur_pos; i>0; i--)
  569.         backspace();
  570.  
  571.     for(i=0; i<max_pos; i++)
  572.         putc(SPACE, stderr);
  573.  
  574.     putc('\r', stderr);
  575.     fputs(prompt, stderr);
  576.  
  577.     cur_pos = 0;
  578.     max_pos = 0;
  579. }
  580.  
  581. /* clear to end of line and the screen end of line */
  582. static void
  583. clear_eoline(prompt)
  584. char *prompt;
  585. {
  586.     int i;
  587.     for(i=cur_pos; i<max_pos; i++)
  588.         cur_line[i] = '\0';
  589.  
  590.     for(i=cur_pos; i<max_pos; i++)
  591.         putc(SPACE, stderr);
  592.     for(i=cur_pos; i<max_pos; i++)
  593.         backspace();
  594. }
  595.  
  596. /* copy line to cur_line, draw it and set cur_pos and max_pos */
  597. static void
  598. copy_line(line)
  599. char *line;
  600. {
  601.     strcpy(cur_line, line);
  602.     user_puts(cur_line);
  603.     cur_pos = max_pos = strlen(cur_line);
  604. }
  605.  
  606. /* add line to the history */
  607. void
  608. add_history(line)
  609. char *line;
  610. {
  611.     struct hist *entry;
  612.     entry = (struct hist *)alloc((unsigned long)sizeof(struct hist),"history");
  613.     entry->line = alloc((unsigned long)(strlen(line)+1),"history");
  614.     strcpy(entry->line, line);
  615.  
  616.     entry->prev = history;
  617.     entry->next = NULL;
  618.     if(history != NULL) {
  619.         history->next = entry;
  620.     }
  621.     history = entry;
  622. }
  623.  
  624.  
  625. /* Convert ANSI arrow keys to control characters */
  626. static char
  627. ansi_getc()
  628. {
  629.   char c = getc(stdin);
  630.   if (c == 033) {
  631.     c = getc(stdin); /* check for CSI */
  632.     if (c == '[') {
  633.       c = getc(stdin); /* get command character */
  634.       switch (c) {
  635.       case 'D': /* left arrow key */
  636.     c = 002;
  637.     break;
  638.       case 'C': /* right arrow key */
  639.     c = 006;
  640.     break;
  641.       case 'A': /* up arrow key */
  642.     c = 020;
  643.     break;
  644.       case 'B': /* down arrow key */
  645.     c = 016;
  646.     break;
  647.       }
  648.     }
  649.   }
  650.   return c;
  651. }
  652.  
  653. #if defined(MSDOS) || defined(_Windows) || defined(DOS386)
  654.  
  655. /* Convert Arrow keystrokes to Control characters: */
  656. static  char
  657. msdos_getch()
  658. {
  659. #ifdef DJGPP
  660.     char c;
  661.     int ch = getkey();
  662.     c = (ch & 0xff00) ? 0 : ch & 0xff;
  663. #else
  664.     char c = getch();
  665. #endif
  666.  
  667.     if (c == 0) {
  668. #ifdef DJGPP
  669.     c = ch & 0xff;
  670. #else
  671.     c = getch(); /* Get the extended code. */
  672. #endif
  673.     switch (c) {
  674.         case 75: /* Left Arrow. */
  675.         c = 002;
  676.         break;
  677.         case 77: /* Right Arrow. */
  678.         c = 006;
  679.         break;
  680.         case 72: /* Up Arrow. */
  681.         c = 020;
  682.         break;
  683.         case 80: /* Down Arrow. */
  684.         c = 016;
  685.         break;
  686.         case 115: /* Ctl Left Arrow. */
  687.         case 71: /* Home */
  688.         c = 001;
  689.         break;
  690.         case 116: /* Ctl Right Arrow. */
  691.         case 79: /* End */
  692.         c = 005;
  693.         break;
  694.         case 83: /* Delete */
  695.         c = 004;
  696.         break;
  697.         default:
  698.         c = 0;
  699.         break;
  700.     }
  701.     }
  702.     else if (c == 033) { /* ESC */
  703.     c = 025;
  704.     }
  705.  
  706.  
  707.     return c;
  708. }
  709.  
  710. #endif /* MSDOS */
  711.  
  712. #ifdef ATARI
  713.  
  714. /* Convert Arrow keystrokes to Control characters: TOS version */
  715.  
  716. /* the volatile could be necessary to keep gcc from reordering 
  717.    the two Super calls
  718. */
  719. #define CONTERM ((/*volatile*/ char *)0x484L)
  720.  
  721. static void 
  722. remove_conterm()
  723. {
  724.   void *ssp=(void*)Super(0L);
  725.   *CONTERM &= ~0x8;
  726.   Super(ssp);
  727. }
  728.  
  729. static    char
  730. tos_getch()
  731. {
  732.     long rawkey;
  733.     char c;
  734.     int scan_code;
  735.     void *ssp;
  736.     static  int init = 1;
  737.     static  int in_help = 0;
  738.  
  739.     if (in_help) {
  740.     switch(in_help) {
  741.         case 1:
  742.         case 5: in_help++; return 'e';
  743.         case 2:
  744.         case 6: in_help++; return 'l';
  745.         case 3:
  746.         case 7: in_help++; return 'p';
  747.         case 4: in_help = 0; return 0x0d;
  748.         case 8: in_help = 0; return ' ';
  749.     }
  750.     }
  751.  
  752.     if (init) {
  753.     ssp = (void*)Super(0L);
  754.     if( !(*CONTERM & 0x8) ) {
  755.         *CONTERM |= 0x8;
  756.     } else {
  757.         init=0;
  758.     }
  759.     (void)Super(ssp);
  760.     if( init ) {
  761.         atexit(remove_conterm);
  762.         init = 0;
  763.     }
  764.     }
  765.  
  766.    (void)Cursconf(1, 0); /* cursor on */
  767.     rawkey = Cnecin();
  768.     c = (char)rawkey;
  769.     scan_code= ((int)(rawkey>>16)) & 0xff;    /* get the scancode */
  770.     if( rawkey&0x07000000 ) scan_code |= 0x80;     /* shift or control */
  771.  
  772.     switch (scan_code) {
  773.     case 0x62:                /* HELP        */
  774.         if (max_pos==0) {
  775.         in_help = 1;
  776.         return 'h';
  777.         } else {
  778.         return 0;
  779.         }
  780.     case 0xe2:                /* shift HELP    */
  781.         if (max_pos==0) {
  782.         in_help = 5;
  783.         return 'h';
  784.         } else {
  785.         return 0;
  786.         }
  787.     case 0x48: /* Up Arrow */
  788.         return 0x10; /* ^P */
  789.     case 0x50: /* Down Arrow */
  790.         return 0x0e; /* ^N */
  791.     case 0x4b: /* Left Arrow */
  792.         return 0x02; /* ^B */
  793.     case 0x4d: /* Right Arrow */
  794.         return 0x06; /* ^F */
  795.     case 0xcb: /* Shift Left Arrow */
  796.     case 0xf3: /* Ctrl Left Arrow (TOS-bug ?) */
  797.     case 0x47: /* Home */
  798.         return 0x01; /* ^A */
  799.     case 0xcd: /* Shift Right Arrow */
  800.     case 0xf4: /* Ctrl Right Arrow (TOS-bug ?) */
  801.     case 0xc7: /* Shift Home */
  802.     case 0xf7: /* Crtl Home */
  803.         return 0x05; /* ^E */
  804.     case 0x61: /* Undo - redraw line */
  805.         return 0x0c; /* ^L */
  806.     default:
  807.         if (c == 0x1b) return 0x15; /* ESC becomes ^U */
  808.         if (c == 0x7f) return 0x04; /* Del becomes ^D */
  809.         break;
  810.     }
  811.  
  812.     return c;
  813. }
  814.  
  815. #endif /* ATARI */
  816.  
  817.   /* set termio so we can do our own input processing */
  818. static void
  819. set_termio()
  820. {
  821. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  822. /* set termio so we can do our own input processing */
  823. /* and save the old terminal modes so we can reset them later */
  824.     if(term_set == 0) {
  825.         /*
  826.          * Get terminal modes.
  827.          */
  828. #ifdef SGTTY
  829.         ioctl(0, TIOCGETP, &orig_termio);
  830. #else  /* SGTTY */
  831. #ifdef TERMIOS
  832. #ifdef TCGETS
  833.         ioctl(0, TCGETS, &orig_termio);
  834. #else
  835.         tcgetattr(0, &orig_termio);
  836. #endif /* TCGETS */
  837. #else
  838.         ioctl(0, TCGETA, &orig_termio);
  839. #endif /* TERMIOS */
  840. #endif /* SGTTY */
  841.  
  842.         /*
  843.          * Save terminal modes
  844.          */
  845.         rl_termio = orig_termio;
  846.  
  847.         /*
  848.          * Set the modes to the way we want them
  849.          *  and save our input special characters
  850.          */
  851. #ifdef SGTTY
  852.         rl_termio.sg_flags |= CBREAK;
  853.         rl_termio.sg_flags &= ~(ECHO|XTABS);
  854.         ioctl(0, TIOCSETN, &rl_termio);
  855.  
  856.         ioctl(0, TIOCGETC, &s_tchars);
  857.         term_chars[VERASE]   = orig_termio.sg_erase;
  858.         term_chars[VEOF]     = s_tchars.t_eofc;
  859.         term_chars[VKILL]    = orig_termio.sg_kill;
  860. #ifdef TIOCGLTC
  861.         ioctl(0, TIOCGLTC, &s_ltchars);
  862.         term_chars[VWERASE]  = s_ltchars.t_werasc;
  863.         term_chars[VREPRINT] = s_ltchars.t_rprntc;
  864.         term_chars[VSUSP]    = s_ltchars.t_suspc;
  865.  
  866.         /* disable suspending process on ^Z */
  867.         s_ltchars.t_suspc = 0;
  868.         ioctl(0, TIOCSLTC, &s_ltchars);
  869. #endif /* TIOCGLTC */
  870. #else  /* SGTTY */
  871.         rl_termio.c_iflag &= ~(BRKINT|PARMRK|INPCK|IUCLC|IXON|IXOFF);
  872.         rl_termio.c_iflag |=  (IGNBRK|IGNPAR);
  873.  
  874.         /* rl_termio.c_oflag &= ~(ONOCR); Costas Sphocleous Irvine,CA */
  875.  
  876.         rl_termio.c_lflag &= ~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|NOFLSH);
  877. #ifdef OS2
  878.  /* for emx: remove default terminal processing */
  879.                 rl_termio.c_lflag &= ~(IDEFAULT);
  880. #endif /* OS2 */
  881.         rl_termio.c_lflag |=  (ISIG);
  882.         rl_termio.c_cc[VMIN] = 1;
  883.         rl_termio.c_cc[VTIME] = 0;
  884.  
  885. #ifndef VWERASE
  886. #define VWERASE 3
  887. #endif
  888.         term_chars[VERASE]   = orig_termio.c_cc[VERASE];
  889.         term_chars[VEOF]     = orig_termio.c_cc[VEOF];
  890.         term_chars[VKILL]    = orig_termio.c_cc[VKILL];
  891. #ifdef TERMIOS
  892.         term_chars[VWERASE]  = orig_termio.c_cc[VWERASE];
  893. #ifdef VREPRINT
  894.         term_chars[VREPRINT] = orig_termio.c_cc[VREPRINT];
  895. #else
  896. #ifdef VRPRNT
  897.         term_chars[VRPRNT] = orig_termio.c_cc[VRPRNT];
  898. #endif
  899. #endif
  900.         term_chars[VSUSP]    = orig_termio.c_cc[VSUSP];
  901.  
  902.         /* disable suspending process on ^Z */
  903.         rl_termio.c_cc[VSUSP] = 0;
  904. #endif /* TERMIOS */
  905. #endif /* SGTTY */
  906.  
  907.         /*
  908.          * Set the new terminal modes.
  909.          */
  910. #ifdef SGTTY
  911.         ioctl(0, TIOCSLTC, &s_ltchars);
  912. #else
  913. #ifdef TERMIOS
  914. #ifdef TCSETSW
  915.         ioctl(0, TCSETSW, &rl_termio);
  916. #else
  917.         tcsetattr(0, TCSADRAIN, &rl_termio);
  918. #endif /* TCSETSW */
  919. #else
  920.         ioctl(0, TCSETAW, &rl_termio);
  921. #endif /* TERMIOS */
  922. #endif /* SGTTY */
  923.         term_set = 1;
  924.     }
  925. #endif /* !MSDOS && !ATARI && !defined(_Windows) */
  926. }
  927.   
  928. static void
  929. reset_termio()
  930. {
  931. #if !defined(MSDOS) && !defined(ATARI) && !defined(_Windows) && !defined(DOS386)
  932. /* reset saved terminal modes */
  933.     if(term_set == 1) {
  934. #ifdef SGTTY
  935.         ioctl(0, TIOCSETN, &orig_termio);
  936. #ifdef TIOCGLTC
  937.         /* enable suspending process on ^Z */
  938.         s_ltchars.t_suspc = term_chars[VSUSP];
  939.         ioctl(0, TIOCSLTC, &s_ltchars);
  940. #endif /* TIOCGLTC */
  941. #else  /* SGTTY */
  942. #ifdef TERMIOS
  943. #ifdef TCSETSW
  944.         ioctl(0, TCSETSW, &orig_termio);
  945. #else
  946.         tcsetattr(0, TCSADRAIN, &orig_termio);
  947. #endif /* TCSETSW */
  948. #else
  949.         ioctl(0, TCSETAW, &orig_termio);
  950. #endif /* TERMIOS */
  951. #endif /* SGTTY */
  952.         term_set = 0;
  953.     }
  954. #endif /* !MSDOS && !ATARI && !_Windows */
  955. }
  956. #endif /* READLINE */
  957.